// Copyright (c) 2005  INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of cgal-python; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; version 2.1 of the License.
// See the file LICENSE.LGPL distributed with cgal-python.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $Id: Py_Constrained_triangulation_2.cpp 167 2007-11-02 15:36:54Z spion $
// $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal-python/trunk/cgal-python/bindings/Triangulations_2/Py_Constrained_triangulation_2.cpp $
//
// Author(s)     : Naceur Meskini
//=========================================================================

// include ====================================================================
#include <CGAL/basic.h>
#include <include/Kernels.h>
#include <include/iterator.h>

#include <CGAL/Constrained_triangulation_2.h>

#include <CGAL/Alpha_shape_vertex_base_2.h>
#include <CGAL/Triangulation_hierarchy_vertex_base_2.h>
#include <CGAL/Triangulation_vertex_base_with_info_2.h>

#include <CGAL/Alpha_shape_face_base_2.h>
#include <CGAL/Delaunay_mesh_face_base_2.h>
#include "Py_Constrained_triangulation_2_doc.h"

// Boost include ==============================================================
#include <boost/python.hpp>
#include <boost/cstdint.hpp>
#include <list>
// Using =======================================================================
using namespace boost::python;

// Declarations ================================================================
namespace  {

	BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(insert_overloads_1_2, insert, 1, 2)
	BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(is_valid_overloads_0_2, is_valid, 0, 2)

}// namespace 

template < class kernel,class Triangulation>
void py_insert(Triangulation& dt,boost::python::list pts)
{
	typedef typename kernel::Point_2 Point_2;
	for(int i = 0 ; i < pts.attr("__len__")() ; i++)
	{
		Point_2 P = boost::python::extract<Point_2>(pts[i]); 
		dt.insert(P);
	}
}
template <class Constrained_triangulation,class Vertex_handle>
boost::python::list py_incident_constraints(const Constrained_triangulation& Ct,Vertex_handle v)
{
	boost::python::list result;
	typedef typename Constrained_triangulation::Edge Edge;
	std::list<Edge> liste;
	Ct.incident_constraints(v, std::back_inserter(liste));
	typename std::list<Edge>::iterator iter;

	for(iter = liste.begin(); iter != liste.end(); iter++)
		result.append(*iter);

	return result;
}
// exporting method ======================================================================
template <class kernel>
void Py_Constrained_triangulation_2()
{
	// three things must be fixed in order to insure the derivation in the python side.
	// -1: the vertex_base 
	// -2: the face_base
	// -3: the data_structure
	typedef CGAL::Alpha_shape_vertex_base_2<kernel> 	Avb;
	typedef CGAL::Triangulation_hierarchy_vertex_base_2<Avb> Hv; //this one is needed when the input data set is huge for the Alpha_shape_2,
																 // say more than 10.000 points,
	typedef CGAL::Triangulation_vertex_base_with_info_2<boost::python::object,kernel,Hv> 	Vb;

	typedef CGAL::Delaunay_mesh_face_base_2<kernel> 	Mf; 
	typedef CGAL::Alpha_shape_face_base_2<kernel,Mf> 	Af;

	typedef CGAL::Triangulation_data_structure_2<Vb,Af> Tds;

	typedef CGAL::Triangulation_2<kernel,Tds>   										Triangulation_2;
	typedef typename Triangulation_2::Edge 												Edge;

	typedef CGAL::Exact_predicates_tag 													Exact_predicates_tag;
	typedef CGAL::Constrained_triangulation_2<kernel,Tds,Exact_predicates_tag>   		Constrained_triangulation_2;
	typedef typename Constrained_triangulation_2::Constraint							Constraint;

	typedef typename Constrained_triangulation_2::Face_handle 							Face_handle;
	typedef typename Constrained_triangulation_2::Vertex_handle 						Vertex_handle;

	typedef typename Triangulation_2::Locate_type 										Locate_type;
	typedef typename kernel::Point_2 													Point_2;
	typedef typename std::list<Edge>::iterator  EdgeIterator;

    class_< Constrained_triangulation_2, bases< Triangulation_2 >  >("Constrained_triangulation_2",Constrained_triangulation_2_doc, init< >())
		.def(init< const Constrained_triangulation_2& >(init_doc))
		.def(init< std::list<Constraint,std::allocator<Constraint > >&, optional< const kernel& > >())
		.def("insert", (Vertex_handle (Constrained_triangulation_2::*)(const Point_2&, Face_handle) )&Constrained_triangulation_2::insert, insert_overloads_1_2(insert_doc))
		.def("insert", (Vertex_handle (Constrained_triangulation_2::*)(const Point_2&, Locate_type, Face_handle, int) )&Constrained_triangulation_2::insert)
		.def("insert",&py_insert<kernel,Constrained_triangulation_2>)
		.def("push_back", (Vertex_handle (Constrained_triangulation_2::*)(const Point_2&) )&Constrained_triangulation_2::push_back)
		.def("insert_constraint", (void (Constrained_triangulation_2::*)(const Point_2&, const Point_2&) )&Constrained_triangulation_2::insert_constraint)
		.def("insert_constraint", (void (Constrained_triangulation_2::*)(Vertex_handle, Vertex_handle) )&Constrained_triangulation_2::insert_constraint,insert_constraint_doc)
		.def("push_back", (void (Constrained_triangulation_2::*)(const Constraint&) )&Constrained_triangulation_2::push_back,push_back_doc)
		.def("remove", &Constrained_triangulation_2::remove,remove_doc)
		.def("remove_constrained_edge",(void (Constrained_triangulation_2::*)(Face_handle, int ))&Constrained_triangulation_2::remove_constrained_edge,remove_constrained_edge_doc)
		.def("remove_incident_constraints", &Constrained_triangulation_2::remove_incident_constraints,remove_incident_constraints_doc)
// 		.def("remove_constraint", &Constrained_triangulation_2::remove_constraint,remove_constraint_doc)
		.def("insert", (void (Constrained_triangulation_2::*)(Point_2, Point_2) )&Constrained_triangulation_2::insert)
		.def("insert", (void (Constrained_triangulation_2::*)(Vertex_handle, Vertex_handle) )&Constrained_triangulation_2::insert)
		.def("is_constrained", &Constrained_triangulation_2::is_constrained,is_constrained_doc)
		.def("are_there_incident_constraints",(bool (Constrained_triangulation_2::*)(Vertex_handle)const )&Constrained_triangulation_2::are_there_incident_constraints,are_there_incident_constraints_doc)
		.def("is_valid", &Constrained_triangulation_2::is_valid, is_valid_overloads_0_2(is_valid_doc))
		.def("incident_constraints",&py_incident_constraints<Constrained_triangulation_2,Vertex_handle>,incident_constraints_doc)
	;
}

void export_Constrained_triangulation_2()
{
	Py_Constrained_triangulation_2<K>();
}
